package nsu.edu.zsq.service.impl.sys;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import nsu.edu.zsq.bean.Course;
import nsu.edu.zsq.bean.CourseExample;
import nsu.edu.zsq.bean.SchMajor;
import nsu.edu.zsq.bean.SchMajorExample;
import nsu.edu.zsq.bean.SchRoomExample;
import nsu.edu.zsq.bean.StuCourseExample;
import nsu.edu.zsq.bean.TchCourse;
import nsu.edu.zsq.bean.TchCourseExample;
import nsu.edu.zsq.bean.Teacher;
import nsu.edu.zsq.bean.TeacherExample;
import nsu.edu.zsq.bean.TeacherExample.Criteria;
import nsu.edu.zsq.common.RequestHolder;
import nsu.edu.zsq.dao.CourseMapper;
import nsu.edu.zsq.dao.SchMajorMapper;
import nsu.edu.zsq.dao.SchRoomMapper;
import nsu.edu.zsq.dao.StuCourseMapper;
import nsu.edu.zsq.dao.TchCourseMapper;
import nsu.edu.zsq.dao.TeacherMapper;
import nsu.edu.zsq.exception.ParamException;
import nsu.edu.zsq.param.PageQuery;
import nsu.edu.zsq.param.TchCourseParam;
import nsu.edu.zsq.service.SchRoomManageService;
import nsu.edu.zsq.service.sys.SysLogService;
import nsu.edu.zsq.service.sys.TeacherCourseService;
import nsu.edu.zsq.util.BeanValidator;

/** 
* Description: 教师课程的service实现类<br>
*/
@Service
public class TeacherCourseServiceImpl implements TeacherCourseService {
    
    @Autowired
    private TeacherMapper teacherMapper;
    @Autowired
    private TchCourseMapper tchCourseMapper;
    @Autowired
    private StuCourseMapper stuCourseMapper;
    @Autowired
    private SysLogService sysLogService;
    @Autowired
    private SchRoomMapper schRoomMapper;
    @Autowired
    private SchMajorMapper schMajorMapper;
    @Autowired
    private CourseMapper courseMapper;
    @Autowired
    private SchRoomManageService schRoomManageService;

    @Override
    public TchCourse getTchCourse(int tchCourseId) {
        TchCourse tchCourse = tchCourseMapper.selectByPrimaryKey(tchCourseId);
        return tchCourse;
    }
    
    @Override
    public List<TchCourseParam> listTchCourse(String teacherNo) {
        List<TchCourseParam> listTchCourse = tchCourseMapper.listTchCourseParamByTeacherNo(teacherNo);
        return listTchCourse;
    }
    
    @Override
    public PageInfo<Teacher> listTeacherWithPage(int orgId, PageQuery pageQuery) {
        // 所有的教师
        int allTeacher = 0;
        PageHelper.startPage(pageQuery.getPageNum(),pageQuery.getPageSize());
        TeacherExample example = new TeacherExample();
        Criteria createCriteria = example.createCriteria();
        // 获取所有没有删除的教师
        createCriteria.andIsDeleteEqualTo(0);
        // 根据排序号，降序
        example.setOrderByClause("sort desc");
        List<Teacher> listTeacher = null;
        if (allTeacher == orgId) {
            listTeacher = teacherMapper.selectByExample(example);
        } else {
            createCriteria.andOrgIdEqualTo(orgId);
            listTeacher = teacherMapper.selectByExample(example);
        }
        PageInfo<Teacher> pageInfo = new PageInfo<Teacher>(listTeacher, pageQuery.getNavigatePages());
        return pageInfo;
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteBatchTchCourse(int[] tchCourseIds) {
        List<TchCourse> before = new ArrayList<TchCourse>();
        for (int tchCourseId : tchCourseIds) {
            TchCourse tchCourse = getTchCourse(tchCourseId);
            before.add(tchCourse);
            tchCourseMapper.deleteByPrimaryKey(tchCourseId);
            // 如果学生与该课程有联系，则不能删除
            if (checkStuCourseExist(tchCourseId)) {
                throw new ParamException("该课程下存在学生，不能执行删除操作");
            }
            // 同时删除掉被占用的教室资源
            schRoomManageService.deleteCourseFromSchRoom(tchCourseId, tchCourse.getCourseType());
        }
        // 添加日志
        String instruction = "教师课程管理-课程管理-批量删除";
        sysLogService.saveSysLogBySysUser(before, null, instruction);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteTchCourse(int tchCourseId) {
        TchCourse before = getTchCourse(tchCourseId);
        tchCourseMapper.deleteByPrimaryKey(tchCourseId);
        // 如果学生与该课程有联系，则不能删除
        if (checkStuCourseExist(tchCourseId)) {
            throw new ParamException("该课程下存在学生，不能执行删除操作");
        }
        // 同时删除掉被占用的教室资源
        schRoomManageService.deleteCourseFromSchRoom(tchCourseId, before.getCourseType());
        // 添加日志
        String instruction = "教师课程管理-课程管理-单个删除";
        sysLogService.saveSysLogBySysUser(before, null, instruction);
    }

    /**
     * 根据教师课程id，检查该教师课程下是否存在学生
     * @param tchCourseId 教师课程id
     * @return boolean true：存在 false：不存在
     */
    private boolean checkStuCourseExist(int tchCourseId) {
        StuCourseExample example = new StuCourseExample();
        example.createCriteria().andTchCourseIdEqualTo(tchCourseId);
        return stuCourseMapper.countByExample(example) > 0;
    }
    
    @Override
    public List<SchMajor> listMajorByOrgId(int orgId) {
        SchMajorExample example = new SchMajorExample();
        example.createCriteria().andOrgIdEqualTo(orgId);
        List<SchMajor> listMajor = schMajorMapper.selectByExample(example);
        return listMajor;
    }

    @Override
    public PageInfo<Course> listCourseByMajorNo(int orgId, String majorNo, PageQuery pageQuery) {
        // 1.获取该院系下所有专业id
        List<SchMajor> listMajor = listMajorByOrgId(orgId);
        List<String> listMajorNo = new ArrayList<String>();
        for (SchMajor schMajor : listMajor) {
            listMajorNo.add(schMajor.getMajorNo());
        }
        // 加上选修课程
        listMajorNo.add("0");
        
        PageHelper.startPage(pageQuery.getPageNum(),pageQuery.getPageSize());
        // 所有课程
        String allCourse = "all";
        // 选修课程
        String publicCourse = "0";
        CourseExample example = new CourseExample();
        // 根据排序号，降序
        example.setOrderByClause("sort desc");
        List<Course> listCourse = null;
        // 2.获取课程数据
        if (allCourse.equals(majorNo)) {
            example.createCriteria().andMajorNoIn(listMajorNo);
            listCourse = courseMapper.selectByExample(example);
        } else if (publicCourse.equals(majorNo)) {
            example.createCriteria().andMajorNoEqualTo(publicCourse);
            listCourse = courseMapper.selectByExample(example);
        } else {
            example.createCriteria().andMajorNoEqualTo(majorNo);
            listCourse = courseMapper.selectByExample(example);
        }
        PageInfo<Course> pageInfo = new PageInfo<Course>(listCourse, pageQuery.getNavigatePages());
        return pageInfo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveBatchCourseToTeacher(String[] courseNos, String teacherNo) {
        List<TchCourse> after = new ArrayList<TchCourse>();
        for (String courseNo : courseNos) {
            // 1.查询课程信息
            CourseExample example = new CourseExample();
            example.createCriteria().andCourseNoEqualTo(courseNo);
            List<Course> course = courseMapper.selectByExample(example);
            TchCourse tchCourse = TchCourse.builder().courseNo(courseNo)
                    .courseName(course.get(0).getCourseName())
                    .courseType(course.get(0).getType()).teacherNo(teacherNo)
                    .operator(RequestHolder.getCurrentSysUser().getAccount())
                    .operatorTime(new Date()).build();
            after.add(tchCourse);
            // 2.检查是否教师存在该课程
            if (checkCourseExist(courseNo, teacherNo)) {
                throw new ParamException("该教师已经存在课程["+course.get(0).getCourseName()+"]");
            }
            // 3.添加课程到教师课程表
            tchCourseMapper.insertSelective(tchCourse);
            // 4.更新教师的课程数量
            updateCourseNum(tchCourse.getTeacherNo());
        }
        
        // 5.添加日志
        String instruction = "教师课程管理-课程管理-添加课程-批量添加";
        sysLogService.saveSysLogBySysUser(null, after, instruction);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveCourseToTeacher(String courseNo, String teacherNo) {
        // 1.查询课程信息
        CourseExample example = new CourseExample();
        example.createCriteria().andCourseNoEqualTo(courseNo);
        List<Course> course = courseMapper.selectByExample(example);
        TchCourse tchCourse = TchCourse.builder().courseNo(courseNo)
                .courseName(course.get(0).getCourseName())
                .courseType(course.get(0).getType()).teacherNo(teacherNo)
                .operator(RequestHolder.getCurrentSysUser().getAccount())
                .operatorTime(new Date()).build();
        // 2.检查是否教师存在该课程
        if (checkCourseExist(courseNo, teacherNo)) {
            throw new ParamException("该教师已经存在课程["+course.get(0).getCourseName()+"]");
        }
        // 3.添加课程到“教师课程”表
        tchCourseMapper.insertSelective(tchCourse);
        // 4.更新教师的课程数量
        updateCourseNum(tchCourse.getTeacherNo());
        
        // 5.添加日志
        String instruction = "教师课程管理-课程管理-添加课程-单个添加";
        sysLogService.saveSysLogBySysUser(null, tchCourse, instruction);
    }

    /**
     * 检查该教师是否已经存在该课程
     * @param courseNo 课程编号
     * @param teacherNo 教师编号
     * @return boolean true：存在 false：不存在
     */
    private boolean checkCourseExist(String courseNo, String teacherNo) {
        TchCourseExample example = new TchCourseExample();
        example.createCriteria().andCourseNoEqualTo(courseNo).andTeacherNoEqualTo(teacherNo);
        return tchCourseMapper.countByExample(example) > 0;
    }
    
    /**
     * 根据教师编号动态更新教师的课程数量
     * @param teacherNo 教师编号
     */
    private void updateCourseNum(String teacherNo) {
        TchCourseExample example = new TchCourseExample();
        example.createCriteria().andTeacherNoEqualTo(teacherNo);
        long courseNum = tchCourseMapper.countByExample(example);
        
        Teacher teacher = Teacher.builder().courseNum((int)courseNum).build();
        TeacherExample teacherExample = new TeacherExample();
        teacherExample.createCriteria().andTeacherNoEqualTo(teacherNo);
        teacherMapper.updateByExampleSelective(teacher, teacherExample);
    }
    
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateTchCourse(TchCourse tchCourse) {
        TchCourse beforeTchCourse = getTchCourse(tchCourse.getId());
        TchCourse before = null;
        tchCourse.setCourseType(beforeTchCourse.getCourseType());
        tchCourse.setOperator(RequestHolder.getCurrentSysUser().getAccount());
        tchCourse.setOperatorTime(new Date());
        if (tchCourse.getNumber() != null) {
            // 1.主修课程：修改每周次数
            before = TchCourse.builder().id(beforeTchCourse.getId()).number(beforeTchCourse.getNumber())
                    .operator(beforeTchCourse.getOperator())
                    .operatorTime(beforeTchCourse.getOperatorTime()).build();
            tchCourseMapper.updateByPrimaryKeySelective(tchCourse);
        } else {
            BeanValidator.check(tchCourse);
            if ((beforeTchCourse.getStartDay() != null && beforeTchCourse.getStartDay().equals(tchCourse.getStartDay()))
                    && (beforeTchCourse.getStartTime() != null && beforeTchCourse.getStartTime().equals(tchCourse.getStartTime()))
                    && (beforeTchCourse.getRoomName() != null && beforeTchCourse.getRoomName().equals(tchCourse.getRoomName()))) {
                // 如果值没变，则直接跳过
                return;
            }
            // 2.选修课程：修改上课时间
            before = TchCourse.builder().id(beforeTchCourse.getId())
                    .roomName(beforeTchCourse.getRoomName())
                    .teacherNo(beforeTchCourse.getTeacherNo())
                    .startDay(beforeTchCourse.getStartDay())
                    .startTime(beforeTchCourse.getStartTime())
                    .stuNumber(beforeTchCourse.getStuNumber())
                    .operator(beforeTchCourse.getOperator())
                    .operatorTime(beforeTchCourse.getOperatorTime()).build();
            // a.检查是否有该教室
            if (!checkRoomNameExist(tchCourse.getRoomName())) {
                throw new ParamException("该教室不存在，请重新输入");
            }
            tchCourse.setTeacherNo(beforeTchCourse.getTeacherNo());
            // b.检查课程是否与该教师时间冲突
            if (checkTimeConflict(tchCourse)) {
                throw new ParamException("与该教师的课程时间冲突");
            }
            // c.删除之前的教室占用
            schRoomManageService.deleteCourseFromSchRoom(tchCourse.getId(), tchCourse.getCourseType());
            // d.更新现在的教室占用
            schRoomManageService.saveCourseToSchRoom(tchCourse);
            // e.修改课程信息
            tchCourseMapper.updateByPrimaryKeySelective(tchCourse);
        }
        // 添加日志
        String instruction = "教师课程管理-课程管理-设置";
        sysLogService.saveSysLogBySysUser(before, tchCourse, instruction);
    }
    
    /**
     * 检查教室是否存在
     * @param roomName 教室名称
     * @return boolean true：存在 false：不存在
     */
    private boolean checkRoomNameExist(String roomName) {
        SchRoomExample example = new SchRoomExample();
        example.createCriteria().andRoomNameEqualTo(roomName);
        return schRoomMapper.countByExample(example) > 0;
    }
    
    /**
     * 判断该教师是否存在课程时间冲突
     * @param tchCourse 教师课程信息
     * @return boolean true：是 false：否
     */
    private boolean checkTimeConflict(TchCourse tchCourse) {
        if (tchCourse.getRoomName() == null || tchCourse.getRoomName().length() <= 0) {
            return false;
        }
        TchCourseExample example = new TchCourseExample();
        example.createCriteria().andTeacherNoEqualTo(tchCourse.getTeacherNo()).andStartDayEqualTo(tchCourse.getStartDay())
            .andStartTimeEqualTo(tchCourse.getStartTime());
        return tchCourseMapper.countByExample(example) > 0;
    }

    @Override
    public List<TchCourseParam> listTchCourseWithCourseTime(String teacherNo) {
        List<TchCourseParam> listTchCourse = tchCourseMapper.listTchCourseWithCourseTime(teacherNo);
        return listTchCourse;
    }
}
